package com.yonghui.summer.code.dao.utils;


import com.yonghui.summer.po.ColumnValue;
import com.yonghui.summer.po.TableMapping;

import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by yangchuan on 17/11/16.
 */
public class SqlBuilderHelper {


    static ConcurrentHashMap<String, TableMapping> tableMaps = new ConcurrentHashMap<>();

    /**
     * 通过类名得到表名
     *
     * @param type
     * @return
     */
    public static String getTableName(Class<?> type) {
        String className = type.getSimpleName();
        return joinByULine(className).toLowerCase();
    }

    public static String getTableName(String classSimpleName) {
        return joinByULine(classSimpleName).toLowerCase();
    }

    /**
     * 通过下划线将单词链接起来
     *
     * @param className
     * @return
     */
    public static String joinByULine(String className) {
        char c;
        int len = className.length();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < len; i++) {
            sb.append(className.charAt(i));

            if (i + 1 < len) {
                c = className.charAt(i + 1);
                if (c < 91 && c > 64) {
                    sb.append("_");
                }
            }
        }
        return sb.toString();
    }

    public static <T> TableMapping getTableMappingCache(Class type) {
        TableMapping cache = tableMaps.get(type.getName());
        if (cache == null) {
            cache = new TableMapping();
            Class clazz = type;

            cache.setTableName(getTableName(clazz));

            ColumnValue item = null;
            BeanInfo beanInfo = null;
            try {
                beanInfo = Introspector.getBeanInfo(clazz, Object.class);
            } catch (IntrospectionException e) {
                throw new IllegalArgumentException("No bean class specified", e);
            }
            PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
            Method readMethod = null;
            for (PropertyDescriptor pd : pds) {
                readMethod = pd.getReadMethod();

                item = new ColumnValue();

                item.setFieldName(pd.getName());

                item.setColumnName(joinByULine(pd.getName()));

                item.setReadMethodName(readMethod.getName());

                cache.getColumnValues().add(item);
            }
            tableMaps.put(type.getClass().getName(), cache);
        }
        return cache;
    }

    public static <T> TableMapping getTableMappingCache(TypeElement type) {
        TableMapping cache = tableMaps.get(type.toString());
        if (cache == null) {
            cache = new TableMapping();
            cache.setTableName(getTableName(type.getSimpleName().toString()));
            ColumnValue item = null;

           String methodName = null;

            for (Element pd : type.getEnclosedElements()) {
                if(pd.getKind() == ElementKind.METHOD){
                    methodName = pd.getSimpleName().toString();
                }else{
                    continue;
                }
                item = new ColumnValue();
                item.setReadMethodName(methodName);
                if(methodName.startsWith("get")){
                    item.setReadMethodName(methodName);
                    item.setFieldName(methodName.substring(3,4).toLowerCase()+methodName.substring(4));
                }else if(methodName.startsWith("is")){
                    item.setReadMethodName(methodName);
                    item.setFieldName(methodName.substring(2,3).toLowerCase()+methodName.substring(3));
                }else{
                    continue;
                }
                item.setColumnName(joinByULine(item.getFieldName()));
                cache.getColumnValues().add(item);
            }
            tableMaps.put(type.getClass().getName(), cache);
        }
        return cache;
    }



}
